
#include "gpt.h"

/*===================== GLOBAL VARIABLES DECLARATION ============================*/
Gpt_ConfigType Gpt_Status;

#pragma DATA_SEG SHARED_DATA
	tCallbackFunction GPT_PIT_ISR_Callback[8];
#pragma DATA_SEG DEFAULT

/*======================== FUNCTION DEFINITIONS =================================*/

/*********************************************************************************
*	Name: Gpt_Init    
*	Type: void                                                                    
*	Parameters: None                                                              
*	Description: Enables Gpt module for the right register parameters
**********************************************************************************/

void Gpt_Init( const Gpt_ConfigType* ConfigPtr ){
	
	/* Pointers to the Configurations registers of the MC*/
	Gpt_ChannelConfigType * ChannelCfg;
	uint8_t channel_counter;
	uint16_t * pitld = (uint16_t *)PITLD0;
	/*First we load predefined configurations por de Micro timers*/	
	PITMTLD0 = CNF_GPT_MICROTIMER_DIV0;
	PITMTLD1 = CNF_GPT_MICROTIMER_DIV1;
	INT_CFADDR         = 0x70;  
    INT_CFDATA4        = 0x03;
	/*Clear Interruption Flags*/
	PITTF = (uint8_t)0xFF; /*Clear all Flags*/
	/*if the configurations parameters are null we will tacke our own configuration parameters*/
	if(NULL == ConfigPtr){
		/* The reference for the configuration is the internal configurations structure*/
		Gpt_Status = Gpt_Config;
	}
	else{
		/* If the reference is not NULL the value for the configurations willl be the ConfigPtr*/
		Gpt_Status = *ConfigPtr;
	}

	for(channel_counter =0; channel_counter < Gpt_Status.NumChannels_pit; channel_counter++){
 		ChannelCfg = &Gpt_Status.ChannelConfigs_pit[channel_counter];
		/* formula to calculate PIT value ( ( CNF_MICROTIMER_PERIODX / PIT_TARGET_FREQ ) - 1 )*/
		if(MICROTIMER_0 == ChannelCfg->microtimer_select)
		{
			PITMUX &= (uint8_t)~(0x01<<ChannelCfg->Channel_ID);
			pitld[ChannelCfg->Channel_ID] =( CNF_MICROTIMER_PERIOD0 / ChannelCfg->target_frequency )-1;
		}
		else
		{
			PITMUX |= (uint8_t)(0x01<<ChannelCfg->Channel_ID);
			pitld[ChannelCfg->Channel_ID] =( CNF_MICROTIMER_PERIOD1 / ChannelCfg->target_frequency )-1;
		}
		if(NOTIFICATION_ENABLE == ChannelCfg->notification_status)
		{
			PITINTE |= (uint8_t)0x01<<ChannelCfg->Channel_ID;
		}

		GPT_PIT_ISR_Callback[ChannelCfg->Channel_ID] = ChannelCfg->Channel_Callback;
	}


}

void Gpt_StartTimer( Gpt_ChannelType Channel, Gpt_ValueType Value ){
	/* Load 8-bit microtimer load register 0 into the 8-bit micro timer down-counter 0 */
	PITCFLMT_PFLMT1 	= 1u;
    PITCFLMT_PFLMT0     = 1u;
    /*TODO*/
     
    /* Load 16-bit timer load register 0 into the 16-bit timer down-counter 0 */
    PITFLT = (uint8_t)0x01<<Channel;
    /* Enable Periodic Interrup Timer */
    PITCE |= (uint8_t)0x01<<Channel;
    /* Enabling PIT */
    PITCFLMT_PITE       = 1u;
}

void Gpt_StopTimer( Gpt_ChannelType Channel ){
	/*Enabling Channel*/
	PITCE &= (uint8_t)~(0x01<<Channel);
}

void Gpt_EnableNotification( Gpt_ChannelType Channel ){
	/* Enable Channel interrupt in PITINTE*/
	PITINTE |= (uint8_t)0x01<<Channel;
}

void Gpt_DisableNotification( Gpt_ChannelType Channel ){
	/* Disable Channel interrupt in PITINTE*/
	PITINTE &= (uint8_t)~(0x01<<Channel);
}


#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt Gpt_Pit_0_Isr(void)
{
	DDRA_DDRA0 = 1u;
	PORTA_PA0 ^= 1;
}

void interrupt Gpt_Pit_1_Isr(void) {
  DDRA_DDRA1 = 1u;
  PORTA_PA1 ^= 1u;
}
#pragma CODE_SEG DEFAULT